/*  This file is part of Real Time Digital Audio Processing library.
 *  Copyright (C) 2008 - Emilio Monti - emilmont@gmail.com
 *
 *  Real Time Digital Audio Processing library is free software: you can
 *  redistribute it and/or modify it under the terms of the GNU General
 *  Public License as published by the Free Software Foundation, either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  Real Time Digital Audio Processing library is distributed in the hope
 *  that it will be useful, but WITHOUT ANY WARRANTY; without even the
 *  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Real Time Audio Processing library.
 *  If not, see <http://www.gnu.org/licenses/>.
 */
#include <stdexcept>
#include <signal.h>
#include <iostream>
#include <time.h>

#include "Audio.h"

using namespace std;

void chk(PaError err) throw(runtime_error) {
    char err_msg[256];
    if (err != paNoError) {
        sprintf(err_msg, "PA Error %d: %s", err, Pa_GetErrorText(err));
        throw runtime_error(err_msg);
    }
}

int callback(void *inBuff, void *outBuff, unsigned long framesPerBuff, PaTimestamp outTime, void *userData) {
    int finished = 0;
    DSP* dsp = (DSP*)userData;
    float* in = (float*)inBuff;
    float* out = (float*)outBuff;
    dsp->callback(in, out, framesPerBuff);

    return finished;
}

void Audio(DSP* dsp, float sec) {
    PortAudioStream *stream;

    try {
        chk(Pa_Initialize());

        PaDeviceID inputDevice;
        int numInputChannels;
        if (dsp->getMic()) {
            inputDevice = Pa_GetDefaultInputDeviceID();
            numInputChannels = 1;
        } else {
            inputDevice = paNoDevice;
            numInputChannels = 0;
        }

        chk(Pa_OpenStream(&stream,
            /* INPUT */
            inputDevice,         /* default input device */
            numInputChannels,      /* no input */
            paFloat32,          /* 32 bit floating point input */
            NULL,

            /* OUTPUT */
            Pa_GetDefaultOutputDeviceID(),
            1,              /* mono output */
            paFloat32,      /* 32 bit floating point output */
            NULL,

            /* STREAM SETTING */
            dsp->getSampleRate(),
            dsp->getFramesPerBuffer(),
            0,                      /* number of buffers, if zero then use default minimum */
            paNoFlag,

            /* DIGITAL SIGNAL PROCESSING */
            callback,
            dsp));

        chk(Pa_StartStream(stream));

        printf("\nPlay for %.3f seconds\n\n", sec); fflush(stdout);
        Pa_Sleep((long)(sec * 1000.0));

        chk(Pa_StopStream(stream));
        chk(Pa_CloseStream(stream));
    }  catch(runtime_error e) {
           cout << e.what() << endl;
    }

    Pa_Terminate();
}
